package com.xuecheng.order.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.xuecheng.commons.constants.OrdersConstants;
import com.xuecheng.commons.enums.ErrorCode;
import com.xuecheng.commons.model.dto.RecordDto;
import com.xuecheng.commons.model.vo.CoursePubIndexVo;
import com.xuecheng.commons.model.vo.OrdersVo;
import com.xuecheng.commons.model.vo.ResponseResult;
import com.xuecheng.commons.utils.AuthInfoHolder;
import com.xuecheng.commons.utils.BeanHelper;
import com.xuecheng.learning.api.LearningClient;
import com.xuecheng.order.config.PayTemplate;
import com.xuecheng.order.domain.Orders;
import com.xuecheng.order.domain.Payment;
import com.xuecheng.order.mapper.OrdersMapper;
import com.xuecheng.order.service.OrdersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.order.service.PaymentService;
import com.xuecheng.search.api.SearchClient;
import com.xuecheng.web.exception.BusinessException;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-12-13
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Autowired
    private SearchClient searchClient;
    // 用户下单
    @Override
    public ResponseResult<String> createOrder(Long coursePubId) {
        // 1.获取TL中用户id
        Long userId = AuthInfoHolder.getUserId();
        // 2.判断用户是否已购买（600002）
        Long count = this.lambdaQuery()
                .eq(Orders::getCoursePubId, coursePubId)
                .eq(Orders::getUserId, userId)
                .eq(Orders::getStatus, OrdersConstants.ORDER_PAID_STATUS).count();
        if (count > 0) {
            throw new BusinessException(ErrorCode.ORDERERROR);
        }
        // 3.判断用户是否已下单（600001）
        Orders orders = this.lambdaQuery()
                .eq(Orders::getCoursePubId, coursePubId)
                .eq(Orders::getUserId, userId)
                .eq(Orders::getStatus, OrdersConstants.ORDER_INIT_STATUS).one();
        if (orders!=null) {
            return ResponseResult.okResult(orders.getOrderNo());
        }
        // 4.封装订单
        orders = new Orders();
        // 4-1 查询课程发布对象
        ResponseResult<CoursePubIndexVo> responseResult = searchClient.findById(coursePubId.toString());
        if (responseResult.getCode()!=0) {
            throw new BusinessException(ErrorCode.PAYERROR);
        }
        CoursePubIndexVo pubIndexVo = responseResult.getData();
        // 4-2 封装参数
        orders.setOrderNo(IdUtil.simpleUUID()); // 32位UUID
        orders.setCoursePubId(pubIndexVo.getCourseId());// 课程id
        orders.setCoursePubName(pubIndexVo.getName());// 课程名称
        orders.setCompanyId(pubIndexVo.getCompanyId()); // 机构id
        orders.setCompanyName(pubIndexVo.getCompanyName());// 机构名称
        orders.setUserId(userId);// 用户id
        orders.setPrice(pubIndexVo.getPrice().longValue());// 订单价格，单位分
        orders.setStatus(OrdersConstants.ORDER_INIT_STATUS); // 订单状态未支付
        orders.setCreateDate(new Date()); // 下单时间
        // 5.保存订单
        this.save(orders);
        // 6.返回订单号
        return ResponseResult.okResult(orders.getOrderNo());
    }

    @Autowired
    private PayTemplate payTemplate;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private LearningClient learningClient;
    // 查询支付结果
    @Override
    @GlobalTransactional
    public ResponseResult<OrdersVo> isPay(String orderNo) {
        // 1.查询微信支付状态
        Boolean checkPayment = payTemplate.checkPayment(orderNo);
        // 2.未支付
        if (checkPayment == false) {
            throw new BusinessException(ErrorCode.NOTPLAY);
        }
        // 3.已支付
        // 3-1 查询订单
        Orders orders = this.lambdaQuery()
                .eq(Orders::getOrderNo, orderNo)
                .one();
        // 3-2 判断订单状态
        if (orders.getStatus().equals(OrdersConstants.ORDER_INIT_STATUS)) {
            // 调用方法更新订单、明细、选课记录
            updatePayStatus(orderNo, orders);
        }
        // 4.订单转vo
        OrdersVo vo = BeanHelper.copyProperties(orders, OrdersVo.class);
        // 5.返回vo
        return ResponseResult.okResult(vo);
    }

    // 查询未支付订单，清理
    @Override
    public void clearOrder() {
        // 1.查询15分钟前未支付订单
        // 1-1 获得前15分钟时间
        Date date = DateUtil.offsetMinute(new Date(), -15).toJdkDate();// 9:46 - 15 = 9:31
        // 1-2 查询数据库
        List<Orders> ordersList = this.lambdaQuery()
                .lt(Orders::getCreateDate, date)
                .eq(Orders::getStatus, OrdersConstants.ORDER_INIT_STATUS)
                .list();
        // 2.遍历再次查询微信，是否支付
        if (CollectionUtil.isNotEmpty(ordersList)) {
            for (Orders orders : ordersList) {
                // 3.查询微信是否付款 二次校验
                Boolean isPay = payTemplate.checkPayment(orders.getOrderNo());
                if (isPay==true) { // 用户已付款
                    // 更新订单、明细状态，保存选课记录
                    updatePayStatus(orders.getOrderNo(),orders);
                }else{ // 用户未付款
                    // 微信关闭订单
                    payTemplate.closeOrder(orders.getOrderNo());
                    // 数据库关闭订单
                    orders.setStatus(OrdersConstants.ORDER_CLOSED_STATUS);
                    this.updateById(orders);

                }
            }
        }else{
            System.out.println("没有超时订单...");
        }
    }

    // 抽取更新订单状态
    private void updatePayStatus(String orderNo, Orders orders) {
        // 更新订单
        orders.setStatus(OrdersConstants.ORDER_PAID_STATUS);
        this.updateById(orders);
        // 更新订单明细
        paymentService.lambdaUpdate()
                .set(Payment::getStatus,"1")
                .eq(Payment::getOrderNo, orderNo)
                .update();

        // 保存选课记录
        RecordDto recordDto = new RecordDto();
        recordDto.setUserId(orders.getUserId()); // 用户id
        recordDto.setCoursePubId(orders.getCoursePubId()); // 课程id
        ResponseResult responseResult = learningClient.saveRecord(recordDto);
        if (responseResult.getCode() != 0) {
            throw new BusinessException(ErrorCode.PARAMSERROR);
        }
    }
}
